from fastapi import APIRouter, UploadFile, File, HTTPException, Response, Form
from fastapi.responses import StreamingResponse, JSONResponse
from typing import List
import io
from app.services import pdf_service
from app.models.response import ApiResponse
from app.utils.file_utils import validate_file_type
from app.config import settings
from app.services.pdf_service import PdfService
import logging

logger = logging.getLogger(__name__)
router = APIRouter()

@router.post(
    "/ocr",
    response_model=ApiResponse,
    summary="PDF/图片OCR识别",
    description="""
    将PDF文档或图片中的文字通过OCR技术识别出来。
    支持的文件格式：PDF、PNG、JPG、JPEG
    支持的识别语言：中文+英文(默认)、仅中文、仅英文
    """,
    response_description="返回识别出的文本内容"
)
async def ocr_pdf(
    file: UploadFile = File(..., description="要识别的PDF或图片文件"),
    lang: str = settings.OCR_LANGUAGES["中文+英文"]
):
    """
    PDF文档或图片OCR识别
    
    Args:
        file: 上传的PDF或图片文件
        lang: OCR识别的语言，默认为中文+英文
    
    Returns:
        ApiResponse: 包含识别结果的响应对象
    
    Raises:
        400: 文件格式不支持或处理失败
    """
    try:
        # 验证文件类型
        if not validate_file_type(file.filename, ['.pdf', '.png', '.jpg', '.jpeg']):
            return ApiResponse(
                code=400,
                message="不支持的文件类型"
            )

        content = await file.read()
        result = await pdf_service.perform_ocr(content, file.filename, lang)
        
        return ApiResponse(data={"text": result})
    except Exception as e:
        return ApiResponse(code=400, message=str(e))

@router.post(
    "/to-word",
    summary="PDF转Word",
    description="""
    将PDF文档转换为可编辑的Word文档。
    - 保持文本内容和基本格式
    - 输出为.docx格式
    - 支持多页PDF转换
    """,
    response_description="返回转换后的Word文档"
)
async def convert_to_word(
    file: UploadFile = File(
        ...,
        description="要转换的PDF文件",
        max_size=settings.MAX_FILE_SIZE
    )
):
    """
    PDF转Word文档
    
    Args:
        file: 上传的PDF文件，大小限制10MB
    
    Returns:
        StreamingResponse: Word文档的文件流
    
    Raises:
        400: 文件格式不支持或转换失败
    """
    try:
        # 验证文件类型
        if not validate_file_type(file.filename, ['.pdf']):
            return ApiResponse(
                code=400,
                message="请上传PDF文件"
            )

        content = await file.read()
        docx_bytes = await pdf_service.pdf_to_word(content)
        
        # 返回文件流
        return StreamingResponse(
            io.BytesIO(docx_bytes),
            media_type="application/vnd.openxmlformats-officedocument.wordprocessingml.document",
            headers={
                "Content-Disposition": f'attachment; filename="converted.docx"'
            }
        )
    except Exception as e:
        return ApiResponse(code=400, message=str(e))

@router.post(
    "/to-ppt",
    summary="PDF转PPT",
    description="""
    将PDF文档转换为PowerPoint演示文稿。
    - 每页PDF转换为一页幻灯片
    - 保持原始图像质量
    - 支持多页转换
    """,
    response_description="返回转换后的PPT文档"
)
async def convert_to_ppt(
    file: UploadFile = File(
        ...,
        description="要转换的PDF文件",
        max_size=settings.MAX_FILE_SIZE
    )
):
    """
    PDF转PPT演示文稿
    
    Args:
        file: 上传的PDF文件，大小限制10MB
    
    Returns:
        StreamingResponse: PPT文档的文件流
    
    Raises:
        400: 文件格式不支持或转换失败
    """
    try:
        if not validate_file_type(file.filename, ['.pdf']):
            return ApiResponse(
                code=400,
                message="请上传PDF文件"
            )

        content = await file.read()
        pptx_bytes = await pdf_service.pdf_to_ppt(content)
        
        return StreamingResponse(
            io.BytesIO(pptx_bytes),
            media_type="application/vnd.openxmlformats-officedocument.presentationml.presentation",
            headers={
                "Content-Disposition": f'attachment; filename="converted.pptx"'
            }
        )
    except Exception as e:
        return ApiResponse(code=400, message=str(e))

@router.post(
    "/images-to-pdf",
    response_class=Response,
    summary="图片转PDF",
    description="""
    将多张图片合并为一个PDF文档。
    - 支持PNG、JPG、JPEG格式
    - 保持原始图片质量
    - 按上传顺序合并
    - 支持多张图片批量处理
    """
)
async def convert_images_to_pdf(
    files: List[UploadFile] = File(
        ...,
        description="要转换的图片文件列表",
        max_size=settings.MAX_FILE_SIZE
    )
):
    try:
        if not files:
            return JSONResponse(
                status_code=400,
                content={"message": "请至少上传一个图片文件"}
            )

        # 验证所有文件
        contents = []
        for file in files:
            if not validate_file_type(file.filename, settings.ALLOWED_EXTENSIONS["image"]):
                return JSONResponse(
                    status_code=400,
                    content={"message": f"不支持的文件格式: {file.filename}"}
                )
            content = await file.read()
            contents.append(content)
            
        result = await PdfService.images_to_pdf(contents)
        
        # 生成输出文件名
        if len(files) == 1:
            output_filename = f"{files[0].filename.rsplit('.', 1)[0]}.pdf"
        else:
            output_filename = "images_converted.pdf"
        
        return Response(
            content=result,
            media_type="application/pdf",
            headers={
                "Content-Disposition": f'attachment; filename="{output_filename}"',
                "Content-Length": str(len(result))
            }
        )
    except ValueError as e:
        logger.error(f"图片转PDF失败: {str(e)}")
        return JSONResponse(
            status_code=400,
            content={"message": str(e)}
        )
    except Exception as e:
        logger.error(f"转换失败: {str(e)}")
        return JSONResponse(
            status_code=500,
            content={"message": "图片转PDF失败，请稍后重试"}
        )

@router.post(
    "/convert",
    response_class=Response,
    summary="转换PDF格式",
    description="将PDF转换为其他格式，或将其他格式转换为PDF"
)
async def convert_pdf(
    file: UploadFile = File(...),
    target_format: str = Form(..., description="目标格式"),
    to_pdf: bool = Form(False, description="是否转换为PDF")
):
    try:
        if not validate_file_type(file.filename, settings.ALLOWED_EXTENSIONS["document"]):
            return JSONResponse(
                status_code=400,
                content={"message": "不支持的文件格式"}
            )
            
        content = await file.read()
        
        if to_pdf:
            source_format = file.filename.split('.')[-1].lower()
            result = await PdfService.convert_to_pdf(content, source_format)
            output_filename = f"{file.filename.rsplit('.', 1)[0]}.pdf"
            media_type = "application/pdf"
        else:
            result = await PdfService.convert_to_format(content, target_format)
            output_filename = f"{file.filename.rsplit('.', 1)[0]}.{target_format}"
            media_type = f"application/{target_format}"
        
        return Response(
            content=result,
            media_type=media_type,
            headers={
                "Content-Disposition": f'attachment; filename="{output_filename}"',
                "Content-Length": str(len(result))
            }
        )
    except ValueError as e:
        return JSONResponse(
            status_code=400,
            content={"message": str(e)}
        )
    except Exception as e:
        logger.error(f"转换失败: {str(e)}")
        return JSONResponse(
            status_code=500,
            content={"message": "转换失败"}
        )

@router.post(
    "/merge",
    response_class=Response,
    summary="合并PDF",
    description="将多个PDF文件合并为一个"
)
async def merge_pdfs(
    files: list[UploadFile] = File(..., description="PDF文件列表"),
):
    """合并多个PDF文件"""
    try:
        if not files:
            return JSONResponse(
                status_code=400,
                content={"message": "请至少上传一个PDF文件"}
            )

        contents = []
        for file in files:
            if not validate_file_type(file.filename, {".pdf"}):
                return JSONResponse(
                    status_code=400,
                    content={"message": f"不支持的文件格式: {file.filename}"}
                )
            content = await file.read()
            contents.append(content)
        
        result = await PdfService.merge_pdfs(contents)
        
        # 生成输出文件名
        if len(files) == 1:
            output_filename = f"{files[0].filename.rsplit('.', 1)[0]}_merged.pdf"
        else:
            output_filename = "merged.pdf"
        
        return Response(
            content=result,
            media_type="application/pdf",
            headers={
                "Content-Disposition": f'attachment; filename="{output_filename}"',
                "Content-Length": str(len(result))
            }
        )
    except ValueError as e:
        logger.error(f"PDF合并失败: {str(e)}")
        return JSONResponse(
            status_code=400,
            content={"message": str(e)}
        )
    except Exception as e:
        logger.error(f"合并失败: {str(e)}")
        return JSONResponse(
            status_code=500,
            content={"message": "PDF合并失败，请稍后重试"}
        )

@router.post(
    "/split",
    response_class=Response,
    summary="拆分PDF",
    description="按页码范围拆分PDF文件"
)
async def split_pdf(
    file: UploadFile = File(...),
    start_page: int = Form(..., description="起始页码"),
    end_page: int = Form(..., description="结束页码")
):
    """
    拆分PDF文件
    """
    try:
        if not validate_file_type(file.filename, {"pdf"}):
            return JSONResponse(
                status_code=400,
                content={"message": "只支持PDF文件"}
            )
        
        content = await file.read()
        result = await PdfService.split_pdf(content, start_page, end_page)
        
        return Response(
            content=result,
            media_type="application/pdf"
        )
    except Exception as e:
        logger.error(f"拆分失败: {str(e)}")
        return JSONResponse(
            status_code=400,
            content={"message": str(e)}
        ) 